!--------------------------------------------------------------------------------------------------!
!   CP2K: A general program to perform molecular dynamics simulations                              !
!   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
!                                                                                                  !
!   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
!--------------------------------------------------------------------------------------------------!

! **************************************************************************************************
!> \par History
!>      10.2005 split input_cp2k into smaller modules [fawzi]
!>      01.2020 add keywords related to Space Groups [pcazade]
!> \author teo & fawzi
! **************************************************************************************************
MODULE input_cp2k_motion
   USE bibliography, ONLY: Brieuc2016, &
                           Byrd1995, &
                           Ceriotti2010, &
                           Ceriotti2012, &
                           Ceriotti2014, &
                           Henkelman1999, &
                           Henkelman2014, &
                           Kapil2016
   USE cp_output_handling, ONLY: add_last_numeric, &
                                 cp_print_key_section_create, &
                                 debug_print_level, &
                                 high_print_level, &
                                 low_print_level, &
                                 medium_print_level
   USE cp_units, ONLY: cp_unit_to_cp2k
   USE input_constants, ONLY: &
      default_bfgs_method_id, default_cell_direct_id, default_cell_geo_opt_id, &
      default_cell_md_id, default_cg_method_id, default_dimer_method_id, &
      default_lbfgs_method_id, default_minimization_method_id, default_ts_method_id, &
      do_mc_gemc_npt, do_mc_gemc_nvt, do_mc_traditional, do_mc_virial, fix_none, fix_x, fix_xy, &
      fix_xz, fix_y, fix_yz, fix_z, fmt_id_pdb, fmt_id_xyz, gaussian, helium_cell_shape_cube, &
      helium_cell_shape_octahedron, helium_forces_average, helium_forces_last, &
      helium_mdist_exponential, helium_mdist_gaussian, helium_mdist_linear, &
      helium_mdist_quadratic, helium_mdist_singlev, helium_mdist_uniform, &
      helium_sampling_ceperley, helium_sampling_worm, helium_solute_intpot_mwater, helium_solute_intpot_nnp, &
      helium_solute_intpot_none, integrate_exact, integrate_numeric, ls_2pnt, ls_3pnt, ls_fit, &
      ls_gold, ls_none, matrix_init_cholesky, matrix_init_diagonal, numerical, perm_cycle, &
      perm_plain, propagator_pimd, propagator_rpmd, propagator_cmd, transformation_normal, transformation_stage
   USE input_cp2k_constraints, ONLY: create_constraint_section
   USE input_cp2k_free_energy, ONLY: create_fe_section
   USE input_cp2k_md, ONLY: create_md_section
   USE input_cp2k_motion_print, ONLY: add_format_keyword, &
                                      create_motion_print_section
   USE input_cp2k_neb, ONLY: create_band_section
   USE input_cp2k_subsys, ONLY: create_rng_section
   USE input_cp2k_thermostats, ONLY: create_coord_section, &
                                     create_gle_section, &
                                     create_velocity_section
   USE input_cp2k_tmc, ONLY: create_TMC_section
   USE input_keyword_types, ONLY: keyword_create, &
                                  keyword_release, &
                                  keyword_type
   USE input_section_types, ONLY: section_add_keyword, &
                                  section_add_subsection, &
                                  section_create, &
                                  section_release, &
                                  section_type
   USE input_val_types, ONLY: integer_t, &
                              logical_t, &
                              real_t, &
                              char_t
   USE kinds, ONLY: dp
   USE string_utilities, ONLY: s2a
#include "../base/base_uses.f90"

   IMPLICIT NONE
   PRIVATE

   LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'input_cp2k_motion'

   PUBLIC :: create_motion_section

CONTAINS

! **************************************************************************************************
!> \brief creates the motion section
!> \param section the section to be created
!> \author teo
! **************************************************************************************************
   SUBROUTINE create_motion_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(section_type), POINTER                        :: subsection

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, __LOCATION__, name="motion", &
                          description="This section defines a set of tool connected with the motion of the nuclei.", &
                          n_keywords=1, n_subsections=1, repeats=.FALSE.)

      NULLIFY (subsection)

      CALL create_geoopt_section(subsection, __LOCATION__, label="GEO_OPT", &
                                 description="This section sets the environment of the geometry optimizer.", &
                                 just_optimizers=.FALSE., &
                                 use_model_hessian=.TRUE.)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_cell_opt_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_shellcore_opt_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_md_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_driver_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_fe_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_constraint_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_fp_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_mc_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_TMC_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_pint_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_band_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_motion_print_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_motion_section

! **************************************************************************************************
!> \brief creates the Monte Carlo section
!> \param section the section to be created
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_mc_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: subsection

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, __LOCATION__, name="mc", &
                          description="This section sets parameters to set up a MonteCarlo calculation.", &
                          n_keywords=10, n_subsections=2, repeats=.FALSE.)

      NULLIFY (keyword, subsection)

      CALL keyword_create(keyword, __LOCATION__, name="NSTEP", &
                          description="Specifies the number of MC cycles.", &
                          usage="NSTEP {integer}", &
                          default_i_val=100)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="IPRINT", &
                          description="Prints coordinate/cell/etc information every IPRINT steps.", &
                          usage="IPRINT {integer}", &
                          default_i_val=1)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="NMOVES", &
                          description="Specifies the number of classical moves between energy evaluations. ", &
                          usage="NMOVES {integer}", &
                          default_i_val=4)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="NSWAPMOVES", &
                          description="How many insertions to try per swap move.", &
                          usage="NSWAPMOVES {integer}", &
                          default_i_val=16)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="LBIAS", &
                          description="Dictates if we presample moves with a different potential.", &
                          usage="LBIAS {logical}", &
                          default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="LSTOP", &
                          description="Makes nstep in terms of steps, instead of cycles.", &
                          usage="LSTOP {logical}", &
                          default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="LDISCRETE", &
                          description="Changes the volume of the box in discrete steps, one side at a time.", &
                          usage="LDISCRETE {logical}", &
                          default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RCLUS", &
                          description="The cluster cut off radius in angstroms.", &
                          usage="RCLUS {real}", &
                          default_r_val=1.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RESTART", &
                          description="Read initial configuration from restart file.", &
                          usage="RESTART {logical}", &
                          default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="NVIRIAL", &
         description="Use this many random orientations to compute the second virial coefficient (ENSEMBLE=VIRIAL)", &
         usage="NVIRIAL {integer}", &
         default_i_val=1000)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="ENSEMBLE", &
                          description="Specify the type of simulation", &
                          usage="ENSEMBLE (TRADITIONAL|GEMC_NVT|GEMC_NPT|VIRIAL)", &
                          enum_c_vals=s2a("TRADITIONAL", "GEMC_NVT", "GEMC_NPT", "VIRIAL"), &
                          enum_i_vals=[do_mc_traditional, do_mc_gemc_nvt, do_mc_gemc_npt, do_mc_virial], &
                          default_i_val=do_mc_traditional)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RESTART_FILE_NAME", &
                          description="Name of the restart file for MC information.", &
                          usage="RESTART_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MOVES_FILE_NAME", &
                          description="The file to print the move statistics to.", &
                          usage="MOVES_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MOLECULES_FILE_NAME", &
                          description="The file to print the number of molecules to.", &
                          usage="MOLECULES_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="COORDINATE_FILE_NAME", &
                          description="The file to print the current coordinates to.", &
                          usage="COORDINATE_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="ENERGY_FILE_NAME", &
                          description="The file to print current energies to.", &
                          usage="ENERGY_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="DATA_FILE_NAME", &
                          description="The file to print current configurational info to.", &
                          usage="DATA_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="CELL_FILE_NAME", &
                          description="The file to print current cell length info to.", &
                          usage="CELL_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_DISP_FILE_NAME", &
                          description="The file to print current maximum displacement info to.", &
                          usage="MAX_DISP_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="BOX2_FILE_NAME", &
                          description="For GEMC, the name of the input file for the other box.", &
                          usage="BOX2_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PRESSURE", &
                          description="The pressure for NpT simulations, in bar.", &
                          usage="PRESSURE {real}", &
                          type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="TEMPERATURE", &
                          description="The temperature of the simulation, in Kelvin.", &
                          usage="TEMPERATURE {real}", &
                          type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="VIRIAL_TEMPS", &
         description="The temperatures you wish to compute the virial coefficient for.  Only used if ensemble=VIRIAL.", &
         usage="VIRIAL_TEMPS {real} {real} ... ", &
         n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="DISCRETE_STEP", &
                          description="The size of the discrete volume move step, in angstroms.", &
                          usage="DISCRETE_STEP {real}", &
                          default_r_val=1.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="ETA", &
                          description="The free energy bias (in Kelvin) for swapping a molecule of each type into this box.", &
                          usage="ETA {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RANDOMTOSKIP", &
                          description="Number of random numbers from the acceptance/rejection stream to skip", &
                          usage="RANDOMTOSKIP {integer}", &
                          default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL create_avbmc_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_move_prob_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_update_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_max_disp_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_mc_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the AVBMC parameters for MC
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_avbmc_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="avbmc", &
                          description="Parameters for Aggregation Volume Bias Monte Carlo (AVBMC) "// &
                          "which explores cluster formation and destruction. "// &
                          "Chen and Siepmann, J. Phys. Chem. B 105, 11275-11282 (2001).", &
                          n_keywords=5, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="PBIAS", &
         description="The probability of swapping to an inner region in an AVBMC swap move for each molecule type.", &
         usage="PBIAS {real} {real} ... ", &
         n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="AVBMC_ATOM", &
                          description="The target atom for an AVBMC swap move for each molecule type.", &
                          usage="AVBMC_ATOM {integer} {integer} ... ", &
                          n_var=-1, type_of_var=integer_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="AVBMC_RMIN", &
                          description="The inner radius for an AVBMC swap move, in angstroms for every molecule type.", &
                          usage="AVBMC_RMIN {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="AVBMC_RMAX", &
                          description="The outer radius for an AVBMC swap move, in angstroms, for every molecule type.", &
                          usage="AVBMC_RMAX {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_avbmc_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the probabilities for attempting each move
!>        type in Monte Carlo
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_move_prob_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: subsection

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="move_probabilities", &
                          description="Parameters for fraction of moves performed for each move type.", &
                          n_keywords=5, n_subsections=2, repeats=.FALSE.)

      NULLIFY (keyword, subsection)

      CALL keyword_create(keyword, __LOCATION__, name="PMHMC", &
                          description="The probability of attempting a hybrid MC move.", &
                          usage="PMHMC {real}", &
                          type_of_var=real_t, default_r_val=0.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMTRANS", &
                          description="The probability of attempting a molecule translation.", &
                          usage="PMTRANS {real}", &
                          type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMCLTRANS", &
                          description="The probability of attempting a cluster translation.", &
                          usage="PMCLTRANS {real}", &
                          type_of_var=real_t, default_r_val=0.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMAVBMC", &
                          description="The probability of attempting an AVBMC swap move.", &
                          usage="PMAVBMC {real}", &
                          default_r_val=0.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMTRAION", &
                          description="The probability of attempting a conformational change.", &
                          usage="PMTRAION {real}", &
                          type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMSWAP", &
                          description="The probability of attempting a swap move.", &
                          usage="PMSWAP {real}", &
                          type_of_var=real_t, default_r_val=0.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMVOLUME", &
                          description="The probability of attempting a volume move.", &
                          usage="PMVOLUME {real}", &
                          type_of_var=real_t, default_r_val=0.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL create_mol_prob_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_box_prob_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_move_prob_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the probabilities for attempting various moves
!>        on the various molecule types present in the system
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_mol_prob_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="mol_probabilities", &
                          description="Probabilities of attempting various moves types on "// &
                          "the various molecular types present in the simulation.", &
                          n_keywords=5, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMAVBMC_MOL", &
                          description="The probability of attempting an AVBMC swap move on each molecule type.", &
                          usage="PMAVBMC_MOL {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMSWAP_MOL", &
                          description="The probability of attempting a molecule swap of a given molecule type.", &
                          usage="PMSWAP_MOL {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMROT_MOL", &
                          description="The probability of attempting a molecule rotation of a given molecule type.", &
                          usage="PMROT_MOL {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMTRAION_MOL", &
                          description="The probability of attempting a conformational change of a given molecule type.", &
                          usage="PMTRAION_MOL {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMTRANS_MOL", &
                          description="The probability of attempting a molecule translation of a given molecule type.", &
                          usage="PMTRANS_MOL {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_mol_prob_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the probabilities for attempting various moves
!>        on the box where the variable is present
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_box_prob_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="BOX_PROBABILITIES", &
                          description="Probabilities of attempting various moves types on "// &
                          "the box.", &
                          n_keywords=2, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMHMC_BOX", &
                          description="The probability of attempting a HMC move on this box.", &
                          usage="PMHMC_BOX {real}", &
                          type_of_var=real_t, default_r_val=1.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMVOL_BOX", &
                          description="The probability of attempting a volume move on this box (GEMC_NpT).", &
                          usage="PMVOL_BOX {real}", &
                          type_of_var=real_t, default_r_val=1.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PMCLUS_BOX", &
                          description="The probability of attempting a cluster move in this box", &
                          usage="PMCLUS_BOX {real}", &
                          type_of_var=real_t, default_r_val=1.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_box_prob_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the frequency for updating maximum
!>        displacements for various moves
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_update_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="MOVE_UPDATES", &
                          description="Frequency for updating move maximum displacements.", &
                          n_keywords=2, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)

      CALL keyword_create(keyword, __LOCATION__, name="IUPVOLUME", &
                          description="Every iupvolume steps update maximum volume displacement.", &
                          usage="IUPVOLUME {integer}", &
                          default_i_val=10000)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="IUPTRANS", &
                          description="Every iuptrans steps update maximum "// &
                          "translation/rotation/configurational changes.", &
                          usage="IUPTRANS {integer}", &
                          default_i_val=10000)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="IUPCLTRANS", &
                          description="Every iupcltrans steps update maximum cluster translation.", &
                          usage="IUPCLTRANS {integer}", &
                          default_i_val=10000)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_update_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the maximum displacements for various moves
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_max_disp_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(section_type), POINTER                        :: subsection

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="max_displacements", &
                          description="The maximum displacements for all attempted moves.", &
                          n_keywords=1, n_subsections=2, repeats=.FALSE.)

      NULLIFY (subsection)

      CALL create_mol_disp_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_box_disp_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_max_disp_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the maximum displacements for all moves which
!>        require a value for each molecule type
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_mol_disp_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="mol_displacements", &
                          description="Maximum displacements for every move type that requires "// &
                          "a value for each molecular type in the simulation.", &
                          n_keywords=5, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMBOND", &
                          description="Maximum bond length displacement, in angstroms, for each molecule type.", &
                          usage="RMBOND {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMANGLE", &
                          description="Maximum bond angle displacement, in degrees, for each molecule type.", &
                          usage="RMANGLE {real} {real} ...", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMDIHEDRAL", &
                          description="Maximum dihedral angle distplacement, in degrees, for each molecule type.", &
                          usage="RMDIHEDRAL {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMROT", &
                          description="Maximum rotational displacement, in degrees, for each molecule type.", &
                          usage="RMROT {real} {real} ... ", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMTRANS", &
                          description="Maximum translational displacement, in angstroms, for each molecule type.", &
                          usage="RMTRANS {real} {real} ...", &
                          n_var=-1, type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_mol_disp_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the maximum displacements for any move that
!>        is done on each simulation box
!> \author matt
! **************************************************************************************************
   SUBROUTINE create_box_disp_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="BOX_DISPLACEMENTS", &
                          description="Maximum displacements for any move that is performed on each"// &
                          " simulation box.", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMVOLUME", &
                          description="Maximum volume displacement, in angstrom**3.", &
                          usage="RMVOLUME {real}", &
                          type_of_var=real_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMCLTRANS", &
                          description="Maximum translational displacement, in angstroms, for each cluster.", &
                          usage="RMCLTRANS {real}", &
                          default_r_val=1.0E0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_box_disp_section

! **************************************************************************************************
!> \brief creates the geometry optimization section
!> \param section the section to be created
!> \param location ...
!> \param label ...
!> \param description ...
!> \param just_optimizers ...
!> \param use_model_hessian ...
!> \par History
!>      01.2020 keywords related to Space Group Symmetry added [pcazade]
!> \author teo
! **************************************************************************************************
   RECURSIVE SUBROUTINE create_geoopt_section(section, location, label, description, just_optimizers, use_model_hessian)
      TYPE(section_type), POINTER                        :: section
      CHARACTER(LEN=*), INTENT(IN)                       :: location, label, description
      LOGICAL, INTENT(IN)                                :: just_optimizers, use_model_hessian

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key, subsection

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, location=location, name=label, description=description, &
                          n_keywords=1, n_subsections=1, repeats=.FALSE.)

      NULLIFY (keyword)
      IF (.NOT. just_optimizers) THEN
         CALL keyword_create(keyword, __LOCATION__, name="TYPE", &
                             description="Specify which kind of geometry optimization to perform", &
                             usage="TYPE (MINIMIZATION|TRANSITION_STATE)", &
                             enum_c_vals=s2a("MINIMIZATION", "TRANSITION_STATE"), &
                             enum_desc=s2a("Performs a geometry minimization.", &
                                           "Performs a transition state optimization."), &
                             enum_i_vals=[default_minimization_method_id, default_ts_method_id], &
                             default_i_val=default_minimization_method_id)
         CALL section_add_keyword(section, keyword)
         CALL keyword_release(keyword)
      END IF

      CALL keyword_create( &
         keyword, __LOCATION__, name="OPTIMIZER", &
         variants=["MINIMIZER"], &
         citations=[Byrd1995], &
         description="Specify which method to use to perform a geometry optimization.", &
         usage="OPTIMIZER {BFGS|LBFGS|CG}", &
         enum_c_vals=s2a("BFGS", "LBFGS", "CG"), &
         enum_desc=s2a("Most efficient minimizer, but only for 'small' systems, "// &
                       "as it relies on diagonalization of a full Hessian matrix", &
                       "Limited-memory variant of BFGS suitable for large systems. "// &
                       "Not as well fine-tuned but can be more robust.", &
                       "conjugate gradients, robust minimizer (depending on the line search) also OK for large systems"), &
         enum_i_vals=[default_bfgs_method_id, default_lbfgs_method_id, default_cg_method_id], &
         default_i_val=default_bfgs_method_id)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_ITER", &
                          description="Specifies the maximum number of geometry optimization steps. "// &
                          "One step might imply several force evaluations for the CG and LBFGS optimizers.", &
                          usage="MAX_ITER {integer}", &
                          default_i_val=200)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_DR", &
                          description="Convergence criterion for the maximum geometry change "// &
                          "between the current and the last optimizer iteration.", &
                          usage="MAX_DR {real}", &
                          default_r_val=0.0030_dp, unit_str="bohr")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_FORCE", &
                          description="Convergence criterion for the maximum force component of the current configuration.", &
                          usage="MAX_FORCE {real}", &
                          default_r_val=0.00045_dp, unit_str="hartree/bohr")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMS_DR", &
                          description="Convergence criterion for the root mean square (RMS) geometry"// &
                          " change between the current and the last optimizer iteration.", &
                          usage="RMS_DR {real}", unit_str="bohr", &
                          default_r_val=0.0015_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RMS_FORCE", &
                          description="Convergence criterion for the root mean square (RMS) force of the current configuration.", &
                          usage="RMS_FORCE {real}", unit_str="hartree/bohr", &
                          default_r_val=0.00030_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="step_start_val", &
                          description="The starting step value for the "//TRIM(label)//" module.", &
                          usage="step_start_val <integer>", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! collects keywords related to Space Group Symmetry
      CALL keyword_create( &
         keyword, __LOCATION__, name="KEEP_SPACE_GROUP", &
         description="Detect space group of the system and preserve it during optimization. "// &
         "The space group symmetry is applied to coordinates, forces, and the stress tensor. "// &
         "It works for supercell. It does not affect/reduce computational cost. "// &
         "Use EPS_SYMMETRY to adjust the detection threshold.", &
         usage="KEEP_SPACE_GROUP .TRUE.", &
         default_l_val=.FALSE., lone_keyword_l_val=.TRUE., repeats=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! collects keywords related to Space Group Symmetry analysis
      CALL keyword_create( &
         keyword, __LOCATION__, name="SHOW_SPACE_GROUP", &
         description="Detect and show space group of the system after optimization. "// &
         "It works for supercell. It does not affect/reduce computational cost. "// &
         "Use EPS_SYMMETRY to adjust the detection threshold.", &
         usage="SHOW_SPACE_GROUP .TRUE.", &
         default_l_val=.FALSE., lone_keyword_l_val=.TRUE., repeats=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! collects keywords related to precision for finding the space group
      CALL keyword_create( &
         keyword, __LOCATION__, name="EPS_SYMMETRY", &
         description="Accuracy for space group determination. EPS_SYMMETRY is dimensionless. "// &
       "Roughly speaking, two scaled (fractional) atomic positions v1, v2 are considered identical if |v1 - v2| < EPS_SYMMETRY. ", &
         usage="EPS_SYMMETRY {REAL}", &
         default_r_val=1.e-4_dp, repeats=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! collects keywords related to reduction of symmetry due to an external field
      CALL keyword_create( &
         keyword, __LOCATION__, name="SYMM_REDUCTION", &
         description="Direction of the external static electric field. "// &
         "Some symmetry operations are not compatible with the direction of an electric field. "// &
         "These operations are used when enforcing the space group.", &
         usage="SYMM_REDUCTION  0.0 0.0 0.0", &
         repeats=.FALSE., n_var=3, &
         type_of_var=real_t, default_r_vals=[0.0_dp, 0.0_dp, 0.0_dp])
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! collects keywords related to ranges of atoms to symmetrize
      CALL keyword_create( &
         keyword, __LOCATION__, name="SYMM_EXCLUDE_RANGE", &
         description="Range of atoms to exclude from space group symmetry. "// &
         "These atoms are excluded from both identification and enforcement. "// &
         "This keyword can be repeated.", &
         repeats=.TRUE., usage="SYMM_EXCLUDE_RANGE {Int} {Int}", type_of_var=integer_t, n_var=2)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="SPGR_PRINT_ATOMS", &
         description="Print equivalent atoms list for each space group symmetry operation.", &
         default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL create_lbfgs_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_cg_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_bfgs_section(subsection, use_model_hessian)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      IF (.NOT. just_optimizers) THEN
         ! Transition states section
         CALL create_ts_section(subsection)
         CALL section_add_subsection(section, subsection)
         CALL section_release(subsection)

         ! Create the PRINT subsection
         NULLIFY (subsection)
         CALL section_create(subsection, __LOCATION__, name="PRINT", &
                             description="Controls the printing properties during a geometry optimization run", &
                             n_keywords=0, n_subsections=1, repeats=.TRUE.)
         NULLIFY (print_key)
         CALL cp_print_key_section_create( &
            print_key, __LOCATION__, "program_run_info", &
            description="Controls the printing of basic information during the Geometry Optimization", &
            print_level=low_print_level, add_last=add_last_numeric, filename="__STD_OUT__")
         CALL section_add_subsection(subsection, print_key)
         CALL section_release(print_key)
         CALL section_add_subsection(section, subsection)
         CALL section_release(subsection)
      END IF

   END SUBROUTINE create_geoopt_section

! **************************************************************************************************
!> \brief creates the section for the shell-core optimization
!> \param section the section to be created
!> \author Caino
! **************************************************************************************************
   SUBROUTINE create_shellcore_opt_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(section_type), POINTER                        :: print_key, subsection

      CALL create_geoopt_section( &
         section, __LOCATION__, label="SHELL_OPT", &
         description="This section sets the environment for the optimization of the shell-core distances"// &
         " that might turn to be necessary along a MD run using a shell-model potential."// &
         " The optimization procedure is activated when at least one of the shell-core"// &
         " pairs becomes too elongated, i.e. when the assumption of point dipole is not longer valid.", &
         just_optimizers=.TRUE., &
         use_model_hessian=.FALSE.)

      NULLIFY (print_key, subsection)

      ! Create the PRINT subsection
      NULLIFY (subsection)
      CALL section_create(subsection, __LOCATION__, name="PRINT", &
                          description="Controls the printing properties during a shell-core optimization procedure", &
                          n_keywords=0, n_subsections=1, repeats=.TRUE.)
      NULLIFY (print_key)
      CALL cp_print_key_section_create(print_key, __LOCATION__, "program_run_info", &
                                       description="Controls the printing of basic information during the Optimization", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="__STD_OUT__")
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_shellcore_opt_section

! **************************************************************************************************
!> \brief creates the section for the cell optimization
!> \param section the section to be created
!> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
! **************************************************************************************************
   SUBROUTINE create_cell_opt_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key, subsection

      CALL create_geoopt_section(section, __LOCATION__, label="CELL_OPT", &
                                 description="This section sets the environment for the optimization of the simulation cell."// &
                                 " Two possible schemes are available: (1) Zero temperature optimization;"// &
                                 " (2) Finite temperature optimization.", &
                                 just_optimizers=.TRUE., &
                                 use_model_hessian=.FALSE.)

      NULLIFY (keyword, print_key, subsection)
      CALL keyword_create( &
         keyword, __LOCATION__, name="TYPE", &
         description="Specify which kind of method to use for the optimization of the simulation cell", &
         usage="TYPE (GEO_OPT|MD|DIRECT_CELL_OPT)", &
         enum_c_vals=s2a("GEO_OPT", "MD", "DIRECT_CELL_OPT"), &
         enum_desc=s2a( &
         "Performs a geometry optimization (the GEO_OPT section must be defined) between cell optimization steps."// &
         " The stress tensor is computed at the optimized geometry.", &
         "Performs a molecular dynamics run (the MD section needs must defined) for computing the stress tensor"// &
         " used for the cell optimization.", &
         "Performs a geometry and cell optimization at the same time."// &
         " The stress tensor is computed at every step"), &
         enum_i_vals=[default_cell_geo_opt_id, default_cell_md_id, default_cell_direct_id], &
         default_i_val=default_cell_direct_id)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="EXTERNAL_PRESSURE", &
         description="Specifies the external pressure (1 value or the full 9 components of the pressure tensor) "// &
         "applied during the cell optimization.", &
         usage="EXTERNAL_PRESSURE {REAL} .. {REAL}", unit_str="bar", &
         default_r_vals=[cp_unit_to_cp2k(100.0_dp, "bar"), 0.0_dp, 0.0_dp, &
                         0.0_dp, cp_unit_to_cp2k(100.0_dp, "bar"), 0.0_dp, &
                         0.0_dp, 0.0_dp, cp_unit_to_cp2k(100.0_dp, "bar")], n_var=-1)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="KEEP_ANGLES", &
         description="Keep angles between the cell vectors constant, but allow the lengths of the"// &
         " cell vectors to change independently."// &
         " Albeit general, this is most useful for triclinic cells, to enforce higher symmetry, see KEEP_SYMMETRY.", &
         usage="KEEP_ANGLES TRUE", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="KEEP_SYMMETRY", &
                          description="Keep the requested initial cell symmetry (e.g. during a cell optimisation). "// &
                          "The initial symmetry must be specified in the &CELL section.", &
                          usage="KEEP_SYMMETRY yes", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="CONSTRAINT", &
         description="Imposes a constraint on the pressure tensor by fixing the specified cell components.", &
         usage="CONSTRAINT (none|x|y|z|xy|xz|yz)", &
         enum_desc=s2a("Fix nothing", &
                       "Fix only x component", &
                       "Fix only y component", &
                       "Fix only z component", &
                       "Fix x and y component", &
                       "Fix x and z component", &
                       "Fix y and z component"), &
         enum_c_vals=s2a("NONE", "X", "Y", "Z", "XY", "XZ", "YZ"), &
         enum_i_vals=[fix_none, fix_x, fix_y, fix_z, fix_xy, fix_xz, fix_yz], &
         default_i_val=fix_none)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PRESSURE_TOLERANCE", &
                          description="Specifies the Pressure tolerance (compared to the external pressure) to achieve "// &
                          "during the cell optimization.", &
                          usage="PRESSURE_TOLERANCE {REAL}", unit_str="bar", &
                          default_r_val=cp_unit_to_cp2k(100.0_dp, "bar"))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! Create the PRINT subsection
      NULLIFY (subsection)
      CALL section_create(subsection, __LOCATION__, name="PRINT", &
                          description="Controls the printing properties during a geometry optimization run", &
                          n_keywords=0, n_subsections=1, repeats=.TRUE.)
      NULLIFY (print_key)
      CALL cp_print_key_section_create(print_key, __LOCATION__, "program_run_info", &
                                       description="Controls the printing of basic information during the Geometry Optimization", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="__STD_OUT__")
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      CALL cp_print_key_section_create(print_key, __LOCATION__, "cell", &
                              description="Controls the printing of the cell eveytime a calculation using a new cell is started.", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="__STD_OUT__", &
                                       unit_str="angstrom")
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_cell_opt_section

! **************************************************************************************************
!> \brief creates the section for tuning transition states search
!> \param section the section to be created
!> \author Teodoro Laino [tlaino] - University of Zurich - 01.2008
! **************************************************************************************************
   SUBROUTINE create_ts_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key, subsection, subsection2, &
                                                            subsection3

! Create the Transition State subsection

      NULLIFY (section, keyword, subsection, subsection2)
      CALL section_create(section, __LOCATION__, name="TRANSITION_STATE", &
                          description="Specifies parameters to perform a transition state search", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="METHOD", &
                          description="Specify which kind of method to use for locating transition states", &
                          citations=[Henkelman1999], &
                          usage="METHOD (DIMER)", &
                          enum_c_vals=s2a("DIMER"), &
                          enum_desc=s2a("Uses the dimer method to optimize transition states."), &
                          enum_i_vals=[default_dimer_method_id], &
                          default_i_val=default_dimer_method_id)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL section_create(subsection, __LOCATION__, name="DIMER", &
                          description="Specifies parameters for Dimer Method", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="DR", &
                          description="This keyword sets the value for the DR parameter.", &
                          usage="DR {real}", unit_str='angstrom', &
                          default_r_val=cp_unit_to_cp2k(0.01_dp, "angstrom"))
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="INTERPOLATE_GRADIENT", &
                          description="This keyword controls the interpolation of the gradient whenever possible"// &
                          " during the optimization of the Dimer. The use of this keywords saves 1 evaluation"// &
                          " of energy/forces.", usage="INTERPOLATE_GRADIENT {logical}", default_l_val=.TRUE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="ANGLE_TOLERANCE", &
                          description="This keyword sets the value of the tolerance angle for the line search"// &
                          " performed to optimize the orientation of the dimer.", &
                          usage="ANGLE_TOLERANCE {real}", unit_str='rad', &
                          default_r_val=cp_unit_to_cp2k(5.0_dp, "deg"))
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="K-DIMER", &
                          description="This keyword activates the constrained k-dimer translation"// &
                          " J. Chem. Phys. 141, 164111 (2014).", &
                          citations=[Henkelman2014], &
                          usage="K-DIMER {logica}", &
                          default_l_val=.FALSE., &
                          lone_keyword_l_val=.FALSE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="BETA", &
                          description="Exponential factor for the switching function used in K-DIMER", &
                          usage="BETA {real}", &
                          default_r_val=5.0_dp, &
                          lone_keyword_r_val=5.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL create_geoopt_section( &
         subsection2, __LOCATION__, label="ROT_OPT", &
         description="This section sets the environment for the optimization of the rotation of the Dimer.", &
         just_optimizers=.TRUE., &
         use_model_hessian=.FALSE.)
      NULLIFY (subsection3)
      CALL section_create(subsection3, __LOCATION__, name="PRINT", &
                          description="Controls the printing properties during the dimer rotation optimization run", &
                          n_keywords=0, n_subsections=1, repeats=.TRUE.)
      NULLIFY (print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "PROGRAM_RUN_INFO", &
                                       description="Controls the printing of basic information during the Geometry Optimization", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="__STD_OUT__")
      CALL section_add_subsection(subsection3, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "ROTATIONAL_INFO", &
                                       description="Controls the printing basic info during the cleaning of the "// &
                                       "rotational degrees of freedom.", print_level=low_print_level, &
                                       add_last=add_last_numeric, filename="__STD_OUT__")
      CALL keyword_create(keyword, __LOCATION__, name="COORDINATES", &
                          description="Prints atomic coordinates after rotation", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(print_key, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection3, print_key)
      CALL section_release(print_key)

      CALL section_add_subsection(subsection2, subsection3)
      CALL section_release(subsection3)
      CALL section_add_subsection(subsection, subsection2)
      CALL section_release(subsection2)

      CALL section_create(subsection2, __LOCATION__, name="DIMER_VECTOR", &
                          description="Specifies the initial dimer vector (used frequently to restart DIMER calculations)."// &
                          " If not provided the starting orientation of the dimer is chosen randomly.", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="_DEFAULT_KEYWORD_", &
                          description="Specify on each line the components of the dimer vector.", repeats=.TRUE., &
                          usage="{Real} {Real} {Real}", type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection2, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, subsection2)
      CALL section_release(subsection2)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_ts_section

! **************************************************************************************************
!> \brief creates the BFGS section
!> \param section the section to be created
!> \param use_model_hessian ...
!> \author Teodoro Laino [tlaino] - University of Zurich - 01.2008
! **************************************************************************************************
   SUBROUTINE create_bfgs_section(section, use_model_hessian)
      TYPE(section_type), POINTER                        :: section
      LOGICAL, INTENT(IN)                                :: use_model_hessian

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key

! create the BFGS subsection

      NULLIFY (section, keyword, print_key)
      CALL section_create(section, __LOCATION__, name="BFGS", &
                          description="Provides parameters to tune the BFGS optimization", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="TRUST_RADIUS", &
                          description="Trust radius used in BFGS. Previously set to 0.1. "// &
                          "Large values can lead to instabilities", &
                          usage="TRUST_RADIUS {real}", unit_str='angstrom', &
                          default_r_val=cp_unit_to_cp2k(0.25_dp, "angstrom"))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="USE_MODEL_HESSIAN", &
                          description="Uses a model Hessian as initial guess instead of a unit matrix."// &
                          " Should lead in general to improved convergence might be switched off for exotic cases", &
                          usage="USE_MODEL_HESSIAN", &
                          default_l_val=use_model_hessian, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="USE_RAT_FUN_OPT", &
                          description="Includes a rational function optimization to determine the step."// &
                          " Previously default but did not improve convergence in many cases", &
                          usage="USE_RAT_FUN_OPT", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RESTART_HESSIAN", &
                          description="Controls the reading of the initial Hessian from file.", &
                          usage="RESTART_HESSIAN", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RESTART_FILE_NAME", &
                          description="Specifies the name of the file used to read the initial Hessian.", &
                          usage="RESTART_FILE_NAME {filename}", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "RESTART", &
                                       description="Controls the printing of Hessian Restart file", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="BFGS", &
                                       common_iter_levels=2)
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

   END SUBROUTINE create_bfgs_section

! **************************************************************************************************
!> \brief creates the CG section
!> \param section the section to be created
!> \author Teodoro Laino [tlaino] - University of Zurich - 01.2008
! **************************************************************************************************
   SUBROUTINE create_cg_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: subsection, subsubsection

! create the CG subsection

      NULLIFY (section, subsection, subsubsection, keyword)
      CALL section_create(section, __LOCATION__, name="CG", &
                          description="Provides parameters to tune the conjugate gradient optimization", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_STEEP_STEPS", &
                          description="Maximum number of steepest descent steps before starting the"// &
                          " conjugate gradients optimization.", &
                          usage="MAX_STEEP_STEPS {integer}", &
                          default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RESTART_LIMIT", &
                          description="Cosine of the angle between two consecutive searching directions."// &
                          " If the angle during a CG optimization is less than the one corresponding to"// &
                          " to the RESTART_LIMIT the CG is reset and one step of steepest descent is"// &
                          " performed.", &
                          usage="RESTART_LIMIT {real}", &
                          default_r_val=0.9_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="FLETCHER_REEVES", &
                          description="Uses FLETCHER-REEVES instead of POLAK-RIBIERE when using Conjugate Gradients", &
                          usage="FLETCHER_REEVES", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! Line Search section
      CALL section_create(subsection, __LOCATION__, name="LINE_SEARCH", &
                          description="Provides parameters to tune the line search during the conjugate gradient optimization", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="TYPE", &
                          description="1D line search algorithm to be used with the CG optimizer,"// &
                          " in increasing order of robustness and cost. ", &
                          usage="TYPE GOLD", &
                          default_i_val=ls_gold, &
                          enum_c_vals=s2a("NONE", "2PNT", "3PNT", "GOLD", "FIT"), &
                          enum_desc=s2a("take fixed length steps", &
                                        "extrapolate based on 2 points", &
                                        "extrapolate based on on 3 points", &
                                        "perform 1D golden section search of the minimum (very expensive)", &
                                        "perform 1D fit of a parabola on several evaluation of energy "// &
                                        "(very expensive and more robust vs numerical noise)"), &
                          enum_i_vals=[ls_none, ls_2pnt, ls_3pnt, ls_gold, ls_fit])
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      ! 2PNT
      NULLIFY (subsubsection)
      CALL section_create(subsubsection, __LOCATION__, name="2PNT", &
                          description="Provides parameters to tune the line search for the two point based line search.", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_ALLOWED_STEP", &
                          description="Max allowed value for the line search step.", &
                          usage="MAX_ALLOWED_STEP {real}", unit_str="internal_cp2k", &
                          default_r_val=0.25_dp)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="LINMIN_GRAD_ONLY", &
         description="Use only the gradient, not the energy for line minimizations (e.g. in conjugate gradients).", &
         usage="LINMIN_GRAD_ONLY T", &
         default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)

      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)

      ! GOLD
      NULLIFY (subsubsection)
      CALL section_create(subsubsection, __LOCATION__, name="GOLD", &
                          description="Provides parameters to tune the line search for the gold search.", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="INITIAL_STEP", &
                          description="Initial step size used, e.g. for bracketing or minimizers. "// &
                          "Might need to be reduced for systems with close contacts", &
                          usage="INITIAL_STEP {real}", unit_str="internal_cp2k", &
                          default_r_val=0.2_dp)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="BRACK_LIMIT", &
                          description="Limit in 1D bracketing during line search in Conjugate Gradients Optimization.", &
                          usage="BRACK_LIMIT {real}", unit_str="internal_cp2k", &
                          default_r_val=100.0_dp)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="BRENT_TOL", &
                          description="Tolerance requested during Brent line search in Conjugate Gradients Optimization.", &
                          usage="BRENT_TOL {real}", unit_str="internal_cp2k", &
                          default_r_val=0.01_dp)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="BRENT_MAX_ITER", &
                          description="Maximum number of iterations in brent algorithm "// &
                          "(used for the line search in Conjugated Gradients Optimization)", &
                          usage="BRENT_MAX_ITER {integer}", &
                          default_i_val=100)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)
   END SUBROUTINE create_cg_section

! **************************************************************************************************
!> \brief creates the LBFGS section
!> \param section the section to be created
!> \author Teodoro Laino [tlaino] - University of Zurich - 01.2008
! **************************************************************************************************
   SUBROUTINE create_lbfgs_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

! create the LBFGS section

      NULLIFY (section, keyword)
      CALL section_create(section, __LOCATION__, name="LBFGS", &
                          description="Provides parameters to tune the limited memory BFGS (LBFGS) optimization", &
                          n_keywords=0, n_subsections=1, repeats=.FALSE., &
                          citations=[Byrd1995])

      CALL keyword_create(keyword, __LOCATION__, name="MAX_H_RANK", &
                          description="Maximum rank (and consequently size) of the "// &
                          "approximate Hessian matrix used by the LBFGS optimizer. "// &
                          "Larger values (e.g. 30) will accelerate the convergence behaviour "// &
                          "at the cost of a larger memory consumption.", &
                          usage="MAX_H_RANK {integer}", &
                          default_i_val=5)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_F_PER_ITER", &
                          description="Maximum number of force evaluations per iteration"// &
                          " (used for the line search)", &
                          usage="MAX_F_PER_ITER {integer}", &
                          default_i_val=20)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="WANTED_PROJ_GRADIENT", &
                          description="Convergence criterion (overrides the general ones):"// &
                          " Requested norm threshold of the gradient multiplied"// &
                          " by the approximate Hessian.", &
                          usage="WANTED_PROJ_GRADIENT {real}", unit_str="internal_cp2k", &
                          default_r_val=1.0E-16_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="WANTED_REL_F_ERROR", &
                          description="Convergence criterion (overrides the general ones):"// &
                          " Requested relative error on the objective function"// &
                          " of the optimizer (the energy)", &
                          usage="WANTED_REL_F_ERROR {real}", unit_str="internal_cp2k", &
                          default_r_val=1.0E-16_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, __LOCATION__, name="TRUST_RADIUS", &
         description="Trust radius used in LBFGS. Not completely in depth tested. Negativ values means no trust radius is used.", &
         usage="TRUST_RADIUS {real}", unit_str='angstrom', &
         default_r_val=-1.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_lbfgs_section

! **************************************************************************************************
!> \brief creates the flexible_partitioning section
!> \param section the section to be created
!> \author Joost VandeVondele [04.2006]
! **************************************************************************************************
   SUBROUTINE create_fp_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, __LOCATION__, name="FLEXIBLE_PARTITIONING", &
                          description="This section sets up flexible_partitioning", &
                          n_keywords=1, n_subsections=1, repeats=.FALSE.)

      NULLIFY (keyword, print_key)

      CALL keyword_create(keyword, __LOCATION__, name="CENTRAL_ATOM", &
                          description="Specifies the central atom.", &
                          usage="CENTRAL_ATOM {integer}", &
                          n_var=1, type_of_var=integer_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="INNER_ATOMS", &
                          description="Specifies the list of atoms that should remain close to the central atom.", &
                          usage="INNER_ATOMS {integer} {integer} .. {integer}", &
                          n_var=-1, type_of_var=integer_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="OUTER_ATOMS", &
                          description="Specifies the list of atoms that should remain far from the central atom.", &
                          usage="OUTER_ATOMS {integer} {integer} .. {integer}", &
                          n_var=-1, type_of_var=integer_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="INNER_RADIUS", &
                          description="radius of the inner wall", &
                          usage="INNER_RADIUS {real} ", type_of_var=real_t, &
                          n_var=1, unit_str="angstrom")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="OUTER_RADIUS", &
                          description="radius of the outer wall", &
                          usage="OUTER_RADIUS {real} ", type_of_var=real_t, &
                          n_var=1, unit_str="angstrom")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="STRENGTH", &
                          description="Sets the force constant of the repulsive harmonic potential", &
                          usage="STRENGTH 1.0", default_r_val=1.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="BIAS", &
                          description="If a bias potential counter-acting the weight term should be applied (recommended).", &
                          usage="BIAS F", default_l_val=.TRUE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="TEMPERATURE", &
                          description="Sets the temperature parameter that is used in the baising potential."// &
                          " It is recommended to use the actual simulation temperature", &
                          usage="TEMPERATURE 300", default_r_val=300.0_dp, unit_str='K')
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SMOOTH_WIDTH", &
                          description="Sets the width of the smooth counting function.", &
                          usage="SMOOTH_WIDTH 0.2", default_r_val=0.02_dp, unit_str='angstrom')
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "WEIGHTS", &
                                       description="Controls the printing of FP info during flexible partitioning simulations.", &
                                       print_level=low_print_level, common_iter_levels=1, &
                                       filename="FLEXIBLE_PARTIONING")
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "CONTROL", &
                                       description="Controls the printing of FP info at startup", &
                                       print_level=low_print_level, common_iter_levels=1, &
                                       filename="__STD_OUT__")
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

   END SUBROUTINE create_fp_section

! **************************************************************************************************
!> \brief ...
!> \param section will contain the driver section
!> \author mceriotti
! **************************************************************************************************
   SUBROUTINE create_driver_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, __LOCATION__, name="DRIVER", &
                          description="This section defines the parameters needed to run in i-PI driver mode.", &
                          citations=[Ceriotti2014, Kapil2016], &
                          n_keywords=3, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, __LOCATION__, name="unix", &
                          description="Use a UNIX socket rather than an INET socket.", &
                          usage="unix LOGICAL", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="port", &
                          description="Port number for the i-PI server.", &
                          usage="port <INTEGER>", &
                          default_i_val=12345)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="host", &
                          description="Host name for the i-PI server.", &
                          usage="host <HOSTNAME>", &
                          default_c_val="localhost")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SLEEP_TIME", &
                          description="Sleeping time while waiting for for driver commands [s].", &
                          usage="SLEEP_TIME 0.1", &
                          default_r_val=0.01_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_driver_section

! **************************************************************************************************
!> \brief creates the section for a path integral run
!> \param section will contain the pint section
!> \author fawzi
! **************************************************************************************************
   SUBROUTINE create_pint_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key, subsection, subsubsection

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, __LOCATION__, name="PINT", &
                          description="The section that controls a path integral run", &
                          n_keywords=13, n_subsections=9, repeats=.FALSE.)
      NULLIFY (keyword)

      CALL keyword_create(keyword, __LOCATION__, name="p", &
                          description="Specify number beads to use", repeats=.FALSE., &
                          default_i_val=3)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="proc_per_replica", &
                          description="Specify number of processors to use for each replica", &
                          repeats=.FALSE., default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="num_steps", &
                          description="Number of steps (if MAX_STEP is not explicitly given"// &
                          " the program will perform this number of steps)", repeats=.FALSE., &
                          default_i_val=3)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="MAX_STEP", &
                          description="Maximum step number (the program will stop if"// &
                          " ITERATION >= MAX_STEP even if NUM_STEPS has not been reached)", &
                          repeats=.FALSE., default_i_val=10)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="iteration", &
                          description="Specify the iteration number from which it should be "// &
                          "counted", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="Temp", &
                          description="The temperature you want to simulate", &
                          default_r_val=cp_unit_to_cp2k(300._dp, "K"), &
                          unit_str="K")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="kT_CORRECTION", &
                          description="Corrects for the loss of temperature due to constrained "// &
                          "degrees of freedom for Nose-Hover chains and numeric integration", &
                          repeats=.FALSE., default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="T_tol", variants=["temp_to"], &
                          description="threshold for the oscillations of the temperature "// &
                          "excedeed which the temperature is rescaled. 0 means no rescaling.", &
                          default_r_val=0._dp, unit_str="K")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="dt", &
                          description="timestep (might be subdivised in nrespa subtimesteps", &
                          repeats=.FALSE., &
                          default_r_val=cp_unit_to_cp2k(1.0_dp, "fs"), &
                          usage="dt 1.0", unit_str="fs")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="HARM_INT", &
                          description="integrator scheme for integrating the harmonic bead springs.", &
                          usage="HARM_INT (NUMERIC|EXACT)", &
                          default_i_val=integrate_numeric, &
                          enum_c_vals=s2a("NUMERIC", "EXACT"), &
                          enum_i_vals=[integrate_numeric, integrate_exact])
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="nrespa", &
                          description="number of respa steps for the bead for each md step", &
                          repeats=.FALSE., default_i_val=5)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="transformation", &
                          description="Specifies the coordinate transformation to use", &
                          usage="TRANSFORMATION (NORMAL|STAGE)", &
                          default_i_val=transformation_normal, &
                          enum_c_vals=s2a("NORMAL", "STAGE"), &
                          enum_i_vals=[transformation_normal, transformation_stage])

      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="propagator", &
                          description="Specifies the real time propagator to use", &
                          usage="PROPAGATOR (PIMD|RPMD|CMD)", &
                          default_i_val=propagator_pimd, &
                          enum_c_vals=s2a("PIMD", "RPMD", "CMD"), &
                          enum_i_vals=[propagator_pimd, propagator_rpmd, propagator_cmd])
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="FIX_CENTROID_POS", &
                          description="Propagate all DOF but the centroid - "// &
                          "useful for equilibration of the non-centroid modes "// &
                          "(activated only if TRANSFORMATION==NORMAL)", &
                          repeats=.FALSE., default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      NULLIFY (subsection, subsubsection)
      CALL section_create(subsection, __LOCATION__, name="NORMALMODE", &
                          description="Controls the normal mode transformation", &
                          n_keywords=3, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="Q_CENTROID", &
                          description="Value of the thermostat mass of centroid degree of freedom", &
                          repeats=.FALSE., default_r_val=-1.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="Q_BEAD", &
                          description="Value of the thermostat mass of non-centroid degrees of freedom", &
                          repeats=.FALSE., default_r_val=-1.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="MODEFACTOR", &
                          description="mass scale factor for non-centroid degrees of freedom", &
                          repeats=.FALSE., default_r_val=1.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="GAMMA", &
                          description="mass scale factor for non-centroid degrees of freedom, &
&                                       naming convention according to Witt, 2008, <https://doi.org/10.1063/1.3125009>.", &
                          repeats=.FALSE., default_r_val=8.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="staging", &
                          description="The section that controls the staging transformation", &
                          n_keywords=2, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="j", &
                          description="Value of the j parameter for the staging transformation", &
                          repeats=.FALSE., default_i_val=2)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="Q_END", &
                          description="Value of the nose-hoover mass for the endbead (Q_end)", &
                          repeats=.FALSE., default_i_val=2)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="BEADS", &
                          description="Sets positions and velocities of the beads", &
                          n_keywords=0, n_subsections=2, &
                          repeats=.FALSE.)
      CALL create_coord_section(subsubsection, "BEADS")
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL create_velocity_section(subsubsection, "BEADS")
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="NOSE", &
                          description="Controls the Nose-Hoover thermostats", &
                          n_keywords=1, n_subsections=2, &
                          repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="nnos", &
                          description="length of nose-hoover chain. 0 means no thermostat", &
                          repeats=.FALSE., default_i_val=2)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL create_coord_section(subsubsection, "NOSE")
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL create_velocity_section(subsubsection, "NOSE")
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_gle_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="PILE", &
                          description="Controls the PI Langevin Equation thermostat."// &
                          " Needs the exact harmonic integrator."// &
                          " May lead to unphysical motions if constraint e.g. FIXED_ATOMS, is applied."// &
                          " RESTART_HELIUM section has to be .FALSE. when restarting the PIGLET job.", &
                          citations=[Ceriotti2010], &
                          n_keywords=3, n_subsections=1, &
                          repeats=.FALSE.)
      CALL create_rng_section(subsubsection)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL keyword_create(keyword, __LOCATION__, name="TAU", &
                          description="Time constant for centroid motion. "// &
                          "If zero or negative the centroid is not thermostated.", &
                          usage="TAU {real}", type_of_var=real_t, &
                          unit_str="fs", n_var=1, default_r_val=1000.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="LAMBDA", &
                          description="Scaling of friction to mode coupling", &
                          usage="LAMBDA {real}", type_of_var=real_t, &
                          n_var=1, default_r_val=0.5_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="THERMOSTAT_ENERGY", &
                          description="Thermostat energy for conserved quantity. "// &
                          "Only useful in restart files.", &
                          usage="THERMOSTAT_ENERGY {real}", type_of_var=real_t, &
                          n_var=1, default_r_val=0.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="PIGLET", &
                          description="Controls the PI Generalized Langevin Equation thermostat."// &
                          " Needs the exact harmonic integrator", &
                          citations=[Ceriotti2012], &
                          n_keywords=4, n_subsections=2, &
                          repeats=.FALSE.)
      CALL create_rng_section(subsubsection)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL section_create(subsubsection, __LOCATION__, name="EXTRA_DOF", &
                          description="Additional degrees of freedom to ensure Markovian Dynamics.", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="_DEFAULT_KEYWORD_", &
                          description="Restart values for additional degrees of freedom" &
                          //" (only for restarts, do not set explicitly)", &
                          repeats=.FALSE., &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL keyword_create(keyword, __LOCATION__, name="NEXTRA_DOF", &
                          description="Number of extra degrees of freedom to ensure markovian dynamics", &
                          repeats=.FALSE., default_i_val=8)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="MATRICES_FILE_NAME", &
                          description="Filename containig the raw matrices from "// &
                          "<https://gle4md.org/index.html?page=matrix>.", &
                          repeats=.FALSE., default_lc_val="PIGLET.MAT")
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="SMATRIX_INIT", &
                          description="Select algorithm to initialize piglet S-matrices", &
                          usage="SMATRIX_INIT (CHOLESKY|DIAGONAL)", &
                          default_i_val=matrix_init_cholesky, &
                          enum_c_vals=s2a("CHOLESKY", "DIAGONAL"), &
                          enum_i_vals=[matrix_init_cholesky, matrix_init_diagonal])
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="THERMOSTAT_ENERGY", &
                          description="Thermostat energy for conserved quantity. "// &
                          "Only useful in restart files.", &
                          usage="THERMOSTAT_ENERGY {real}", type_of_var=real_t, &
                          n_var=1, default_r_val=0.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="QTB", &
                          description="Controls the QTB-PILE thermostat."// &
                          " Needs the exact harmonic integrator", &
                          citations=[Brieuc2016], &
                          n_keywords=7, n_subsections=1, &
                          repeats=.FALSE.)
      CALL create_rng_section(subsubsection)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL keyword_create(keyword, __LOCATION__, name="TAU", &
                          description="Time constant for centroid motion. ", &
                          usage="TAU {real}", type_of_var=real_t, &
                          unit_str="fs", n_var=1, default_r_val=1000.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="LAMBDA", &
                          description="Scaling of friction to ring polymer NM freq.", &
                          usage="LAMBDA {real}", type_of_var=real_t, &
                          n_var=1, default_r_val=0.5_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="FP", &
                          description="Defines which version to use "// &
                          "0: f_P^(0), 1: f_P^(1)", &
                          usage="FP {integer}", type_of_var=integer_t, &
                          n_var=1, default_i_val=1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="TAUCUT", &
                          description="Inverse of cutoff freq. for the centroid mode", &
                          usage="TAUCUT {real}", type_of_var=real_t, &
                          unit_str="fs", n_var=1, default_r_val=0.5_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="LAMBCUT", &
                          description="Scaling of cutoff freq. to ring polymer NM freq.", &
                          usage="LAMBCUT {real}", type_of_var=real_t, &
                          n_var=1, default_r_val=2.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="NF", &
                          description="Number of points used for the convolution product.", &
                          usage="NF {integer}", type_of_var=integer_t, &
                          n_var=1, default_i_val=128)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="THERMOSTAT_ENERGY", &
                          description="Thermostat energy for conserved quantity. "// &
                          "Only useful in restart files.", &
                          usage="THERMOSTAT_ENERGY {real}", type_of_var=real_t, &
                          n_var=1, default_r_val=0.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="INIT", &
                          description="Controls the initialization if the beads are not present", &
                          repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="LEVY_POS_SAMPLE", &
                          description="Sample bead positions assuming free particle "// &
                          "behavior (performs a Levy random walk of length P around "// &
                          "the classical position of each atom at the physical "// &
                          "temperature defined in PINT%TEMP)", &
                          repeats=.FALSE., default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="LEVY_CORRELATED", &
                          description="Use the same Levy path for all atoms, though "// &
                          "with mass-dependent variances (might help at very low T)", &
                          repeats=.FALSE., default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="LEVY_TEMP_FACTOR", &
                          description="Multiplicative correction factor for the "// &
                          "temperature at which the Levy walk is performed "// &
                          "(correction is due to the interactions that modify "// &
                          "the spread of a free particle)", &
                          repeats=.FALSE., default_r_val=1.0_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="LEVY_SEED", &
                          description="Initial seed for the (pseudo)random number "// &
                          "generator that controls Levy walk for bead positions.", &
                          usage="LEVY_SEED <INTEGER>", default_i_val=1234, &
                          repeats=.FALSE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="THERMOSTAT_SEED", &
                          description="Initial seed for the (pseudo)random number "// &
                          "generator that controls the PILE and PIGLET thermostats.", &
                          usage="THERMOSTAT_SEED <INTEGER>", default_i_val=12345, &
                          repeats=.FALSE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="RANDOMIZE_POS", &
                          description="add gaussian noise to the positions of the beads", &
                          repeats=.FALSE., default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="CENTROID_SPEED", &
                          description="adds random velocity component to the centroid modes "// &
                          "(useful to correct for the averaging out of the speed of various beads)", &
                          repeats=.FALSE., default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="VELOCITY_QUENCH", &
                          description="set the initial velocities to zero", &
                          repeats=.FALSE., default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="VELOCITY_SCALE", &
                          description="scale initial velocities to the temperature given in MOTION%PINT%TEMP", &
                          repeats=.FALSE., default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_helium_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="PRINT", &
                          description="Controls the path integral-specific output", &
                          n_keywords=2, n_subsections=0, repeats=.FALSE.)

      NULLIFY (print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "ENERGY", &
                                       description="Controls the output of the path integral energies", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "ACTION", &
                                       description="Controls the output of the path integral action", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "CENTROID_POS", &
                                       description="Controls the output of the centroid's position", &
                                       unit_str="angstrom", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL add_format_keyword(keyword, print_key, pos=.TRUE., &
                              description="Output file format for the positions of centroid")
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "CENTROID_VEL", &
                                       description="Controls the output of the centroid's velocity", &
                                       unit_str="bohr*au_t^-1", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL add_format_keyword(keyword, print_key, pos=.FALSE., &
                              description="Output file format for the velocity of centroid")
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "CENTROID_GYR", &
                                       description="Controls the output of the centroid's radii of gyration", &
                                       unit_str="angstrom", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "COM", &
                                       description="Controls the output of the center of mass", &
                                       print_level=high_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL keyword_create(keyword, __LOCATION__, name="IMAGINARY_TIME_STRIDE", &
                          description="Prints only every nth bead trajectory", &
                          repeats=.FALSE., default_i_val=1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_pint_section

   ! ***************************************************************************
   !> \brief  Create the input section for superfluid helium solvent.
   !> \author Lukasz Walewski
   ! ***************************************************************************
! **************************************************************************************************
!> \brief ...
!> \param section ...
! **************************************************************************************************
   SUBROUTINE create_helium_section(section)
      TYPE(section_type), POINTER                        :: section

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key, subsection, subsubsection

      CPASSERT(.NOT. ASSOCIATED(section))

      CALL section_create(section, __LOCATION__, name="HELIUM", &
                          description="The section that controls optional helium solvent"// &
                          " environment (highly experimental, not for general use yet)", &
                          n_keywords=31, n_subsections=11, repeats=.FALSE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, __LOCATION__, name="_SECTION_PARAMETERS_", &
                          description="Whether or not to actually use this section", &
                          usage="silent", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="HELIUM_ONLY", &
                          description="Simulate helium solvent only, "// &
                          "disregard solute entirely", &
                          repeats=.FALSE., default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="INTERACTION_POT_SCAN", &
                          description="Scan solute-helium interaction potential, "// &
                          "cubefile parameters set in subsection RHO", &
                          repeats=.FALSE., default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="NUM_ENV", &
                          description="Number of independent helium environments", &
                          repeats=.FALSE., default_i_val=1)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="POTENTIAL_FILE_NAME", &
                          description="Name of the Helium interaction potential file", &
                          repeats=.FALSE., default_lc_val="HELIUM.POT")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="GET_FORCES", &
                          description="Get average MC forces or last MC forces to propagate MD", &
                          usage="GET_FORCES (AVERAGE|LAST)", &
                          default_i_val=helium_forces_average, &
                          enum_c_vals=s2a("AVERAGE", "LAST"), &
                          enum_i_vals=[helium_forces_average, helium_forces_last])
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SOLUTE_INTERACTION", &
                          description="Interaction potential between helium and the solute", &
                          usage="SOLUTE_INTERACTION (NONE | MWATER | NNP)", &
                          default_i_val=helium_solute_intpot_none, &
                          enum_c_vals=s2a("NONE", "MWATER", "NNP"), &
                          enum_i_vals=[ &
                          helium_solute_intpot_none, &
                          helium_solute_intpot_mwater, &
                          helium_solute_intpot_nnp], &
                          enum_desc=s2a( &
                          "No interaction with solute", &
                          "Test interaction with wrong Water", &
                          "Interaction with NNP"))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="NATOMS", &
                          description="Number of helium atoms", &
                          repeats=.FALSE., default_i_val=64)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="NBEADS", &
                          description="Number of helium path integral beads", &
                          repeats=.FALSE., default_i_val=25)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RNG_SEED", &
                          description="Initial seed for the (pseudo)random number "// &
                          "generator that controls helium coordinate generation and propagation.", &
                          usage="RNG_SEED <INTEGER>", default_i_val=12345, &
                          repeats=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="N_INNER", &
                          variants=s2a("INOROT"), &
                          description="Number of MC iterations at the same time slice(s) "// &
                          "(number of inner MC loop iterations)", &
                          repeats=.FALSE., default_i_val=6600)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="N_OUTER", &
                          variants=s2a("IROT"), &
                          description="how often to reselect the time slice(s) to work on "// &
                          "(number of outer MC loop iterations)", &
                          repeats=.FALSE., default_i_val=300)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SAMPLING_METHOD", &
                          description="Choose between Ceperley or the worm algorithm", &
                          usage="SAMPLING_METHOD (CEPERLEY|WORM)", &
                          default_i_val=helium_sampling_ceperley, &
                          enum_c_vals=s2a("CEPERLEY", "WORM"), &
                          enum_i_vals=[helium_sampling_ceperley, helium_sampling_worm])
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="COORD_INIT_TEMP", &
                          description="Temperature for thermal gaussian initialization of the helium."// &
                          " Negative values correspond to a hot start.", &
                          default_r_val=cp_unit_to_cp2k(300._dp, "K"), &
                          unit_str="K")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SOLUTE_RADIUS", &
                          description="Radius of the solute molecule for prevention of"// &
                          " coordinate collision during initialization", &
                          default_r_val=cp_unit_to_cp2k(0.0_dp, "angstrom"), &
                          repeats=.FALSE., type_of_var=real_t, unit_str="angstrom")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! Helium-solute interaction NNP
      NULLIFY (subsection)
      CALL section_create(subsection, __LOCATION__, name="NNP", &
                          description="This section contains all information to run an helium-solute "// &
                          "interaction Neural Network Potential (NNP) calculation.", &
                          n_keywords=2, n_subsections=3, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="NNP_INPUT_FILE_NAME", &
                          description="File containing the input information for the setup "// &
                          "of the NNP (n2p2/RuNNer format). ", &
                          repeats=.FALSE., default_lc_val="input.nn")
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SCALE_FILE_NAME", &
                          description="File containing the scaling information for the symmetry "// &
                          "functions of the NNP. ", &
                          repeats=.FALSE., default_lc_val="scaling.data")
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      NULLIFY (subsubsection)
      CALL section_create(subsubsection, __LOCATION__, name="SR_CUTOFF", &
                          description="Section for failsafe short range cutoffs for the NNPs, "// &
                          "if the distance between solvent and specified solute element becomes "// &
                          "smaller than the given cutoff, an artifical repulsive potential is "// &
                          "introduced. Note this is only meant to prevent such configurations, "// &
                          "not to physically sample them.", &
                          n_keywords=2, n_subsections=0, repeats=.TRUE.)

      CALL keyword_create(keyword, __LOCATION__, name="ELEMENT", &
                          description="Solute element for which the short range cutoff is in effect", &
                          repeats=.FALSE., default_c_val="none")
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="RADIUS", &
                          description="Short range cutoff in Angstrom, below this cutoff, the energy "// &
                          "is replaced by a sizable positive value plus a 1/r**2 term to guide particles "// &
                          "away from each other.", &
                          default_r_val=cp_unit_to_cp2k(0.0_dp, "angstrom"), &
                          repeats=.FALSE., type_of_var=real_t, unit_str="angstrom")
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)

      NULLIFY (subsubsection)
      CALL section_create(subsubsection, __LOCATION__, name="MODEL", &
                          description="Section for a single NNP model. If this section is repeated, "// &
                          "a committee model (C-NNP)is used where the NNP members share the same "// &
                          "symmetry functions. ", &
                          n_keywords=1, n_subsections=0, repeats=.TRUE.)

      CALL keyword_create(keyword, __LOCATION__, name="WEIGHTS", &
                          description="File containing the weights for the artificial neural "// &
                          "networks of the NNP. The specified name is extended by .XXX.data ", &
                          repeats=.FALSE., default_lc_val="weights")
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)

      ! Create the PRINT subsection
      NULLIFY (subsubsection)
      CALL section_create(subsubsection, __LOCATION__, name="PRINT", &
                          description="Section of possible print options in NNP code.", &
                          n_keywords=0, n_subsections=3, repeats=.FALSE.)
      NULLIFY (print_key, keyword)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "ENERGIES", &
                                       description="Controls the printing of the NNP energies.", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsubsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "FORCES_SIGMA", &
                                       description="Controls the printing of the STD per atom of the NNP forces.", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsubsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "EXTRAPOLATION", &
                                       description="If activated, output structures with extrapolation "// &
                                       "warning in xyz-format", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsubsection, print_key)
      CALL section_release(print_key)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection) ! release NNP subsection

      ! Ceperley's sampling algorithm
      NULLIFY (subsection)
      CALL section_create(subsection, __LOCATION__, name="CEPERLEY", &
                          description="Enables sampling with Ceperley's algorithm", &
                          n_keywords=2, n_subsections=1, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="BISECTION", &
                          description="how many time slices to change at once (+1). "// &
                          "Must be a power of 2 currently", &
                          repeats=.FALSE., default_i_val=8)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_PERM_CYCLE", &
                          description="how large cyclic permutations to try", &
                          repeats=.FALSE., default_i_val=6)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      NULLIFY (subsubsection)
      CALL section_create(subsubsection, __LOCATION__, name="M-SAMPLING", &
                          description="Permutation cycle length sampling settings", &
                          n_keywords=3, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="DISTRIBUTION-TYPE", &
                          description="Distribution from which the cycle length m is sampled", &
                          usage="DISTRIBUTION-TYPE (SINGLEV|UNIFORM|LINEAR|QUADRATIC|EXPONENTIAL|GAUSSIAN)", &
                          default_i_val=helium_mdist_uniform, &
                          enum_c_vals=s2a( &
                          "SINGLEV", &
                          "UNIFORM", &
                          "LINEAR", &
                          "QUADRATIC", &
                          "EXPONENTIAL", &
                          "GAUSSIAN"), &
                          enum_i_vals=[ &
                          helium_mdist_singlev, &
                          helium_mdist_uniform, &
                          helium_mdist_linear, &
                          helium_mdist_quadratic, &
                          helium_mdist_exponential, &
                          helium_mdist_gaussian])
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="M-VALUE", &
                          description="Value of m treated in a special way "// &
                          "(specific behavior depends on the distribution type chosen)", &
                          repeats=.FALSE., &
                          default_i_val=1)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="M-RATIO", &
                          description="Probability ratio betw M-VALUE and other cycle lengths", &
                          repeats=.FALSE., &
                          default_r_val=1.0_dp)
      CALL section_add_keyword(subsubsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, subsubsection)
      CALL section_release(subsubsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection) ! release CEPERLEY subsection

! worm algorithm parameters:
      NULLIFY (subsection)
      CALL section_create(subsection, __LOCATION__, name="WORM", &
                          description="Enables sampling via the canonical worm algorithm adapted from Bonisegni", &
                          n_keywords=12, n_subsections=0, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="CENTROID_DRMAX", &
                          description="Maximum displacement allowed for the centroid moves", &
                          repeats=.FALSE., default_r_val=0.5_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="STAGING_L", &
                          description="From 2 up to max. L-1 beads will be moved", &
                          repeats=.FALSE., default_i_val=5)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="OPEN_CLOSE_SCALE", &
                          description="Open/Close acceptance adjustment parameter", &
                          repeats=.FALSE., default_r_val=0.01_dp)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="ALLOW_OPEN", &
                          description="Enable bosonic exchange sampling", &
                          repeats=.FALSE., default_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAX_OPEN_CYCLES", &
                         description="If > 0 then reset positions and permutations to the previous closed &
                         & state if staying more than this amount of MC cycles in open state to avoid staying &
                         & trapped in open state for too long. Use with caution as it can potentially introduce &
                         & a bias in the sampling.", &
                          repeats=.FALSE., default_i_val=0)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SHOW_STATISTICS", &
                          description="Show sampling statistics in output", &
                          repeats=.FALSE., default_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="CENTROID_WEIGHT", &
                          description="Absolute weight of the centroid move", &
                          repeats=.FALSE., default_i_val=10)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="STAGING_WEIGHT", &
                          description="Absolute weight of the staging move", &
                          repeats=.FALSE., default_i_val=30)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="OPEN_CLOSE_WEIGHT", &
                          description="Absolute weight of the open/close move", &
                          repeats=.FALSE., default_i_val=10)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="HEAD_TAIL_WEIGHT", &
                          description="Absolute weight of the head/tail moves (both)", &
                          repeats=.FALSE., default_i_val=10)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="CRAWL_WEIGHT", &
                          description="Absolute weight of the crawl bwd/fwd moves (both)", &
                          repeats=.FALSE., default_i_val=10)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="CRAWL_REPETITION", &
                          description="Number of repeated crawl moves", &
                          repeats=.FALSE., default_i_val=4)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SWAP_WEIGHT", &
                          description="Absolute weight of the crawl move", &
                          repeats=.FALSE., default_i_val=10)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection) ! release WORM subsection

! end of worm parameters

      CALL keyword_create(keyword, __LOCATION__, name="PERIODIC", &
                          description="Use periodic boundary conditions for helium", &
                          repeats=.FALSE., default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="CELL_SIZE", &
                          description="PBC unit cell size (NOTE 1: density, number of atoms"// &
                          " and volume are interdependent - give only two of them; "// &
                          "NOTE 2: for small cell sizes specify NATOMS instead)", &
                          repeats=.FALSE., type_of_var=real_t, unit_str="angstrom")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="CELL_SHAPE", &
                          description="PBC unit cell shape for helium", &
                          usage="CELL_SHAPE (CUBE|OCTAHEDRON)", &
                          default_i_val=helium_cell_shape_cube, &
                          enum_c_vals=s2a("CUBE", "OCTAHEDRON"), &
                          enum_i_vals=[helium_cell_shape_cube, helium_cell_shape_octahedron])
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="DROPLET_RADIUS", &
                          description="Reject a move if any of the new positions does not lie within"// &
                          "  this range from the center of gravity", &
                          repeats=.FALSE., type_of_var=real_t, default_r_val=HUGE(1.0_dp), &
                          unit_str="angstrom")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="DENSITY", &
                          description="trial density of helium for determining the helium "// &
                          "box size", &
                          repeats=.FALSE., &
                          default_r_val=cp_unit_to_cp2k(0.02186_dp, "angstrom^-3"), &
                          unit_str="angstrom^-3")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="PRESAMPLE", &
                          description="Presample He coordinates before first PIMD step", &
                          repeats=.FALSE., default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL section_create(subsection, __LOCATION__, name="RDF", &
                          description="Radial distribution settings", &
                          n_keywords=5, n_subsections=0, repeats=.FALSE.)

      CALL keyword_create(keyword, __LOCATION__, name="_SECTION_PARAMETERS_", &
                          description="Whether or not to actually calculate this property", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="MAXR", &
                          description="Maximum RDF range, defaults to unit cell size", &
                          repeats=.FALSE., type_of_var=real_t, &
                          unit_str="angstrom")
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="NBIN", &
                          description="Number of bins", &
                          repeats=.FALSE., &
                          default_i_val=250)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="SOLUTE_HE", &
                          description="Whether or not to calculate solute-He RDFs (if solute is present)", &
                          default_l_val=.TRUE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, __LOCATION__, name="HE_HE", &
                          description="Whether or not to calculate He-He RDFs", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      NULLIFY (subsection)
      CALL section_create(subsection, __LOCATION__, name="RHO", &
                          description="Spatial distribution settings", &
                          n_keywords=10, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="_SECTION_PARAMETERS_", &
                          description="Whether or not to actually calculate densities "// &
                          "(requires significant amount of memory, depending on the value of NBIN)", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="NBIN", &
                          description="Number of grid points in each direction for density binning", &
                          repeats=.FALSE., &
                          default_i_val=100)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="MIN_CYCLE_LENGTHS_WDG", &
                          description="Density of winding paths "// &
                          "not shorter than the given length", &
                          repeats=.FALSE., usage="MIN_CYCLE_LENGTHS_WDG <INT> <INT> .. <INT>", &
                          type_of_var=integer_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="MIN_CYCLE_LENGTHS_NON", &
                          description="Density of non-winding paths "// &
                          "not shorter than the given length", &
                          repeats=.FALSE., usage="MIN_CYCLE_LENGTHS_NON <INT> <INT> .. <INT>", &
                          type_of_var=integer_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="MIN_CYCLE_LENGTHS_ALL", &
                          description="Density of all paths "// &
                          "not shorter than the given length", &
                          repeats=.FALSE., usage="MIN_CYCLE_LENGTHS_ALL <INT> <INT> .. <INT>", &
                          type_of_var=integer_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="ATOM_NUMBER", &
                          description="Atom number density", &
                          repeats=.FALSE., &
                          type_of_var=logical_t, &
                          default_l_val=.TRUE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="PROJECTED_AREA_2", &
                          description="Projected area squared density, A*A(r)", &
                          repeats=.FALSE., &
                          type_of_var=logical_t, &
                          default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="WINDING_NUMBER_2", &
                          description="Winding number squared density, W*W(r)", &
                          repeats=.FALSE., &
                          type_of_var=logical_t, &
                          default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="WINDING_CYCLE_2", &
                          description="Winding number squared density, W^2(r)", &
                          repeats=.FALSE., &
                          type_of_var=logical_t, &
                          default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      !
      CALL keyword_create(keyword, __LOCATION__, name="MOMENT_OF_INERTIA", &
                          description="Moment of inertia density", &
                          repeats=.FALSE., &
                          type_of_var=logical_t, &
                          default_l_val=.FALSE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)
      ! end of subsection RHO

      CALL create_coord_section(subsection, "HELIUM")
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="PERM", &
                          description="Permutation state used for restart", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="_DEFAULT_KEYWORD_", &
                          description="Specify particle index permutation for every "// &
                          "helium atom", repeats=.TRUE., usage="<INT> <INT> .. <INT>", &
                          type_of_var=integer_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="AVERAGES", &
                          description="Average properties (used for restarts)", &
                          n_keywords=7, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="PROJECTED_AREA", &
                          description="Projected area vector for all environments", &
                          repeats=.TRUE., usage="PROJECTED_AREA <REAL> <REAL> .. <REAL>", &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="PROJECTED_AREA_2", &
                          description="Projected area vector squared for all environments", &
                          repeats=.TRUE., usage="PROJECTED_AREA_2 <REAL> <REAL> .. <REAL>", &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="WINDING_NUMBER_2", &
                          description="Winding number vector squared for all environments", &
                          repeats=.TRUE., usage="WINDING_NUMBER_2 <REAL> <REAL> .. <REAL>", &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="MOMENT_OF_INERTIA", &
                          description="Moment of inertia vector for all environments", &
                          repeats=.TRUE., usage="MOMENT_OF_INERTIA <REAL> <REAL> .. <REAL>", &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="RDF", &
                          description="Radial distributions averaged over all environments", &
                          repeats=.TRUE., usage="RDF <REAL> <REAL> .. <REAL>", &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="RHO", &
                          description="Spatial distributions averaged over all environments", &
                          repeats=.TRUE., usage="RHO <REAL> <REAL> .. <REAL>", &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, __LOCATION__, name="IWEIGHT", &
                          description="Weight for the restarted quantities "// &
                          "(number of MC steps used to calculate the accumulated averages)", &
                          repeats=.FALSE., &
                          default_i_val=0)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="FORCE", &
                          description="Forces exerted by the helium on the solute system"// &
                          " (used for restarts)", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="_DEFAULT_KEYWORD_", &
                          description="Number of real values should be 3 * "// &
                          "<num_solute_atoms> * <num_solute_beads>", repeats=.TRUE., &
                          usage="<REAL> <REAL> .. <REAL>", type_of_var=real_t, &
                          n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="RNG_STATE", &
                          description="Random number generator state for all processors", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)
      CALL keyword_create(keyword, __LOCATION__, name="_DEFAULT_KEYWORD_", &
                          description="Three real arrays of DIMENSION(3,2) times two RNG "// &
                          "streams - 36 real values per processor", &
                          repeats=.TRUE., usage="automatically filled, do not edit by hand", &
                          type_of_var=real_t, n_var=-1)
      CALL section_add_keyword(subsection, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL section_create(subsection, __LOCATION__, name="PRINT", &
                          description="The section that controls the output of the helium code", &
                          n_keywords=16, n_subsections=0, repeats=.FALSE.)

      ! *************************************************************************
      !> Printkeys for properties output
      ! *************************************************************************
      NULLIFY (print_key)

      ! Properties printed at SILENT print level
      !

      ! Properties printed at LOW print level
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "ENERGY", &
                                       description="Controls the output of helium energies"// &
                                       " (averaged over MC step)", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "PROJECTED_AREA_2_AVG", &
                                       description="Controls the output of the average projected area squared vector", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "WINDING_NUMBER_2_AVG", &
                                       description="Controls the output of the average winding number vector squared", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "MOMENT_OF_INERTIA_AVG", &
                                       description="Controls the output of the average moment of inertia vector", &
                                       print_level=low_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      ! Properties printed at MEDIUM print level
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "RDF", &
                                       description="Controls the output of helium radial distribution functions", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "RHO", &
                                       description="Controls the output of the helium density "// &
                                       "(Gaussian cube file format)", &
                                       each_iter_names=s2a("PINT"), each_iter_values=[100], &
                                       print_level=medium_print_level, common_iter_levels=1, &
                                       add_last=add_last_numeric)
      CALL keyword_create(keyword, __LOCATION__, name="BACKUP_COPIES", &
                          description="Specifies the maximum number of backup copies.", &
                          usage="BACKUP_COPIES {int}", &
                          default_i_val=1)
      CALL section_add_keyword(print_key, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "PROJECTED_AREA", &
                                       description="Controls the output of the projected area vector", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "WINDING_NUMBER", &
                                       description="Controls the output of the winding number vector", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "MOMENT_OF_INERTIA", &
                                       description="Controls the output of the moment of inertia vector", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "PLENGTH", &
                                       description="Controls the output of the helium permutation length", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "ACTION", &
                                       description="Controls the output of the total helium action", &
                                       print_level=medium_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      ! Properties printed at HIGH print level
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "COORDINATES", &
                                       description="Controls the output of helium coordinates", &
                                       print_level=high_print_level, common_iter_levels=1)
      CALL keyword_create(keyword, __LOCATION__, name="FORMAT", &
                          description="Output file format for the coordinates", &
                          usage="FORMAT (PDB|XYZ)", &
                          default_i_val=fmt_id_pdb, &
                          enum_c_vals=s2a("PDB", "XYZ"), &
                          enum_i_vals=[fmt_id_pdb, fmt_id_xyz], &
                          enum_desc=s2a("Bead coordinates and connectivity is written in PDB format", &
                                        "Only bead coordinates are written in XYZ format"))
      CALL section_add_keyword(print_key, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "PERM", &
                                       description="Controls the output of the helium permutation state", &
                                       print_level=high_print_level, common_iter_levels=1)
      CALL keyword_create(keyword, __LOCATION__, name="FORMAT", &
                          description="Output format for the permutation", &
                          usage="FORMAT (CYCLE|PLAIN)", &
                          default_i_val=perm_cycle, &
                          enum_c_vals=s2a("CYCLE", "PLAIN"), &
                          enum_i_vals=[perm_cycle, perm_plain], &
                          enum_desc=s2a( &
                          "Cycle notation with winding cycles enclosed"// &
                          " in '[...]' and non-winding ones enclosed in '(...)'", &
                          "Plain permutation output, i.e. P(1) ... P(N)"))
      CALL section_add_keyword(print_key, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, __LOCATION__, "FORCES", &
                                       description="Controls the output of the helium forces on the solute", &
                                       print_level=high_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      ! Properties printed at DEBUG print level
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "ACCEPTS", &
                                       description="Controls the output of the helium acceptance data", &
                                       print_level=debug_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)
      !
      CALL cp_print_key_section_create(print_key, __LOCATION__, "FORCES_INST", &
                                       description="Controls the output of the instantaneous helium forces on the solute", &
                                       print_level=debug_print_level, common_iter_levels=1)
      CALL section_add_subsection(subsection, print_key)
      CALL section_release(print_key)

      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      RETURN
   END SUBROUTINE create_helium_section

END MODULE input_cp2k_motion
